#region License, Terms and Conditions
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
#endregion
using System;
using System.Web.Mvc;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.RelyingParty;
using raya.Models.login;
using raya.Models.openid;

namespace raya.Controllers
{
    public class loginController : baseController
    {
        public ActionResult Index()
        {
            object error = "";
            if (Session["id"] != null)
            {
                return Redirect(Request.QueryString["redirect"] ?? "/home");
            }
            if (Request.Form.Count != 0)
            {
                if (!String.IsNullOrEmpty(Request.Form["login_email"]) && !String.IsNullOrEmpty(Request.Form["login_password"]))
                {
                    // registration went ok, set up the session (and cookie)
                    if (Authenticate(Request.Form["login_email"], Request.Form["login_password"]))
                    {
                        return Redirect(Request.QueryString["redirect"] ?? "/home");
                    }
                    error = "Invalid email / password combination.";
                }
                else
                {
                    error = "Please fill in your email and password.";
                }
            }
            return View("login", error);

        }

        /// <summary>
        /// handle openid logins
        /// </summary>
        /// <param name="param1">returnURL</param>
        /// <returns></returns>
        public ActionResult Openid(string param1)
        {
            openID thisO = new openID();
            var openid = new OpenIdRelyingParty();
            var response = openid.GetResponse();
            if (response == null)
            {
                Identifier id;
                string stringid = Request.QueryString["openid_url"] ?? Request.Form["openid_identifier"];
                if (!stringid.StartsWith("http"))
                {
                    throw new Exception("unknown OpenID format: " + stringid);
                }
                // Stage 2: user submitting Identifier

                if (Identifier.TryParse(stringid, out id))
                {
                    try
                    {
                        var request = openid.CreateRequest(stringid);
                        
                        // only ask for extra info if this user is new
                        if (!thisO.doesOpenIDExist(stringid))
                        {
                            // do this for anything that does not have an explicit openid known by the user 
                            //
                            if (Request.QueryString["openid_url"] != null)
                            {
                                var ext = new FetchRequest();
                                ext.Attributes.AddRequired(WellKnownAttributes.Contact.Email);
                                ext.Attributes.AddRequired(WellKnownAttributes.Name.First);
                                ext.Attributes.AddRequired(WellKnownAttributes.Name.Last);
                                ext.Attributes.AddRequired(WellKnownAttributes.Preferences.Language);
                                ext.Attributes.AddRequired(WellKnownAttributes.Contact.HomeAddress.Country);
                                request.AddExtension(ext);
                                /*
                                OAuthExtensionRequest oauth = new OAuthExtensionRequest();
                                oauth.ConsumerKey = "my6solutions.com";
                                oauth.Scope = "http://www.google.com/m8/feeds/";
                                request.AddExtension(oauth);
                                */
                            }
                            else
                            {
                                var claimsReq = new ClaimsRequest
                                                    {
                                                        BirthDate = DemandLevel.Request,
                                                        Nickname = DemandLevel.Request,
                                                        PostalCode = DemandLevel.Request,
                                                        Language = DemandLevel.Request,
                                                        TimeZone = DemandLevel.Request,
                                                        Country = DemandLevel.Request,
                                                        Email = DemandLevel.Require,
                                                        FullName = DemandLevel.Request,
                                                        Gender = DemandLevel.Request
                                                    };
                                request.AddExtension(claimsReq);
                            }
                        }

                        return request.RedirectingResponse.AsActionResult();
                    }
                    catch (ProtocolException ex)
                    {
                        return View("Login", (object)ex.Message);
                    }
                }
                return View("Login", (object)"Invalid identifier");
            }

            // Stage 3: OpenID Provider sending assertion response
            switch (response.Status)
            {
                case AuthenticationStatus.Authenticated:
                    var friendlyIdentifier = response.FriendlyIdentifierForDisplay;
                
                    // find if this openid exists
                    var userid = thisO.getUserID("http://" + friendlyIdentifier);
                    login u = null;
                    string email = null;
                    if (string.IsNullOrEmpty(userid))
                    {
                        var claimsExt = response.GetExtension<ClaimsResponse>();
                        if (claimsExt == null)
                        {
                            var fetchExt = response.GetExtension<FetchResponse>();
                            if (fetchExt != null && 
                                fetchExt.Attributes.Contains(WellKnownAttributes.Contact.Email))
                            {
                                email = fetchExt.Attributes[WellKnownAttributes.Contact.Email].Values[0];
                            }
                        }
                        else
                        {
                            email = claimsExt.Email;
                        }
                        
                        // maybe user is already registered on this site
                        // see if we can get a user account based on email address
                        u = login.GetUserByEmail(email);
                        if (u == null)
                        {
                            if (claimsExt != null)
                            {
                                userid = thisO.add_new_openid_user("http://" + friendlyIdentifier, claimsExt).ToString();
                            }
                            else
                            {
                                // need to handle this
                            }
                        }
                        else
                        {
                            // just create new openid user
                            thisO.AttachOpenID("http://" + friendlyIdentifier, u.id);
                        }
                    }

                    if (string.IsNullOrEmpty(userid))
                    {
                        // unable to login user
                        return View("Login", (object) "Unable to sign in. Please register an account.");
                    }

                    // login user
                    if (u == null)
                    {
                        // only will be hit on new user entry
                        u = login.GetUserByEmail(userid);
                    }
                    u.SetSession(Session);

                    if (!string.IsNullOrEmpty(param1))
                    {
                        return Redirect(param1);
                    }
                    return RedirectToAction("Index", "Home");
                case AuthenticationStatus.Canceled:
                    return View("Login", (object)"Canceled at provider");
                case AuthenticationStatus.Failed:
                    return View("Login", (object)response.Exception.Message);
            }
            return new EmptyResult();
        }



    }
}